package com.aliyun.heiyu.powermaster.server.strategy;

import com.aliyun.heiyu.common.util.DateUtil;
import com.aliyun.heiyu.powermaster.proto.PowerStrategy;
import com.aliyun.heiyu.powermaster.proto.StrategyAction;
import com.aliyun.heiyu.powermaster.server.MasterConstant;
import com.aliyun.heiyu.powermaster.server.strategy.analyzer.AnalyzerContext;
import com.aliyun.heiyu.powermaster.server.util.ZkClientUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.TimeUnit;

public class StrategyContext {
    private static Logger logger = LoggerFactory.getLogger(StrategyContext.class);

    private AnalyzerContext analyzerContext;
    private Map<String, Map<String, StrategyAction>> analyzeType2SN2Action;
    private StrategyActor actor;

    public StrategyContext(){
        this.analyzerContext = new AnalyzerContext();
        this.actor = new StrategyActor();
        logger.info("strategy monitor start");
        bootStrategy();
    }

    public static void main(String[] args){
        System.out.println(new DateUtil().getStringDate(new Date()));
        StrategyContext context = new StrategyContext();
        if(context.check()){
            context.act();
        }
        System.out.println(new DateUtil().getStringDate(new Date()));
    }

    private void bootStrategy(){
        Runnable task = new Runnable() {
            @Override
            public void run() {
                try {
                    logger.debug("strategy task going...");
                    if(check()){
                        if (ZkClientUtil.checkLeader()) {
                            act();
                        }
                    }
                }catch (Throwable t){
                    logger.error(t.getMessage(),t);
                }
            }
        };
        StrategyExecutor.getInstance().getScheduledThreadPool().scheduleAtFixedRate(task,60,
            2,TimeUnit.SECONDS);
    }

    /**检查*/
    public boolean check(){
        analyzeType2SN2Action = analyzerContext.getAnalyzeType2SN2Action();
        logger.debug("策略动作集合     "+analyzeType2SN2Action);
        return analyzeType2SN2Action.size() > 0;
    }

    /**执行*/
    public void act(){
        actionConflict();

        List<String> list = Arrays.asList(MasterConstant.AI_DVFS, MasterConstant.AI_CSTATE, MasterConstant.AI_POWEROFF, MasterConstant.AI_CAPPING, MasterConstant.CAPPING);

        for(String analyzeType : list){
            //执行动作
            Map<String, StrategyAction> sn2Action = analyzeType2SN2Action.get(analyzeType);
            if(sn2Action == null){
                continue;
            }
            if(MasterConstant.CAPPING.equals(analyzeType)){
                actor.capping(sn2Action);
            }else if(MasterConstant.AI_CAPPING.equals(analyzeType)){
                actor.aiCapping(sn2Action);
            }else if(MasterConstant.AI_DVFS.equals(analyzeType)){
                actor.dvfs(sn2Action);
            }else if(MasterConstant.AI_CSTATE.equals(analyzeType)){
                actor.cstate(sn2Action);
            }else if(MasterConstant.AI_POWEROFF.equals(analyzeType)){
                actor.powerOff(sn2Action);
            }

        }
    }

    // 手动策略 的capping poweroff 会与自动策略冲突为解决
    private void actionConflict(){
        Map<String, StrategyAction> map1 = analyzeType2SN2Action.get(MasterConstant.AI_CAPPING);
        Map<String, StrategyAction> map2 = analyzeType2SN2Action.get(MasterConstant.CAPPING);
        if(map1 != null && map1.size() > 0 && map2 != null && map2.size() > 0){
            Set<String> set1 = map1.keySet();
            Set<String> set2 = map2.keySet();
            for(String sn : set1){
                if(set2.contains(sn)){
                    StrategyAction action1 = map1.get(sn);
                    StrategyAction action2 = map2.get(sn);
                    if(action1.getActionName().equals(action2.getActionName())){
                        //都为uncpping的情况
                        map1.remove(sn);
                    } else {
                        //一个capping，一个uncapping的情况
                        if(PowerStrategy.CAPPING_POWER.equals(action1.getActionName())){
                            map2.remove(sn);
                        } else {
                            map1.remove(sn);
                        }
                    }
                }
            }
            analyzeType2SN2Action.put(MasterConstant.AI_CAPPING,map1);
            analyzeType2SN2Action.put(MasterConstant.CAPPING,map2);
        }

    }

}
